﻿//===================================================================================
// Copyright (c) Ryan Garrett.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===================================================================================

using System;
using System.Collections.Generic;

namespace Caffeine.Core.Test.TestModel.PropertyRegistrations
{
    public class ModelForPropertyTesting : ModelBase
    {
        #region State

        private readonly ModelProperty<Int32> _unconstrainedInt32;
        private readonly ModelProperty<Nullable<Int32>> _unconstrainedNullableInt32;
        private readonly ModelProperty<String> _stringProperty;
        private readonly ModelProperty<String> _stringProperty2;
        private readonly ModelProperty<String> _stringProperty3;
        private readonly ModelProperty<String> _stringProperty4;
        private readonly ModelProperty<String> _stringProperty5;
        private readonly ModelProperty<String> _stringProperty6;
        private readonly ModelProperty<Int32> _int32Property;
        private readonly ModelProperty<Int32> _int32Property2;
        private readonly ModelProperty<Int32> _int32Property3;
        private readonly ModelProperty<Int32> _int32Property4;
        private readonly ModelProperty<Int32> _int32Property5;
        private readonly ModelProperty<Nullable<UInt32>> _nullableUInt32Property;
        private readonly ModelProperty<Nullable<UInt32>> _nullableUInt32Property2;
        private readonly ModelProperty<Nullable<UInt32>> _nullableUInt32Property3;
        private readonly ModelProperty<Nullable<UInt32>> _nullableUInt32Property4;
        private readonly ModelProperty<Nullable<UInt32>> _nullableUInt32Property5;
        private readonly ModelProperty<EnumForTesting> _enumProperty;
        private readonly ModelProperty<EnumForTesting> _enumProperty2;
        private readonly ModelProperty<EnumForTesting> _enumProperty3;
        private readonly ModelProperty<EnumForTesting> _enumProperty4;
        private readonly ModelProperty<EnumForTesting> _enumProperty5;
        private readonly ModelProperty<Nullable<EnumForTesting>> _nullableEnumProperty;
        private readonly ModelProperty<Nullable<EnumForTesting>> _nullableEnumProperty2;
        private readonly ModelProperty<Nullable<EnumForTesting>> _nullableEnumProperty3;
        private readonly ModelProperty<Nullable<EnumForTesting>> _nullableEnumProperty4;
        private readonly ModelProperty<Nullable<EnumForTesting>> _nullableEnumProperty5;
        private readonly ModelProperty<String> _computedStringProperty;
        private readonly ModelProperty<String> _computedStringProperty2;
        private readonly ModelProperty<String> _computedStringProperty3;
        private readonly ModelProperty<String> _computedStringProperty4;
        private readonly ModelProperty<String> _computedStringProperty5;
        private readonly ModelProperty<Int32> _computedInt32Property;
        private readonly ModelProperty<Int32> _computedInt32Property2;
        private readonly ModelProperty<Int32> _computedInt32Property3;
        private readonly ModelProperty<Int32> _computedInt32Property4;
        private readonly ModelProperty<Int32> _computedInt32Property5;
        private readonly ModelProperty<String[]> _stringArrayProperty;
        private readonly ModelProperty<String[]> _stringArrayProperty2;
        private readonly ModelProperty<String[]> _stringArrayProperty3;
        private readonly ModelProperty<String[]> _stringArrayProperty4;
        private readonly ModelProperty<String[]> _stringArrayProperty5;
        private readonly ModelProperty<IEnumerable<String>> _enumerableProperty;
        private readonly ModelProperty<IEnumerable<String>> _enumerableProperty2;
        private readonly ModelProperty<IEnumerable<String>> _enumerableProperty3;
        private readonly ModelProperty<IEnumerable<String>> _enumerableProperty4;
        private readonly ModelProperty<IEnumerable<String>> _enumerableProperty5;
        private readonly ModelProperty<ModelWithNoProperties> _childModelProperty;
        private readonly ModelProperty<ModelWithNoProperties> _childModelProperty2;
        private readonly ModelProperty<ModelWithNoProperties> _childModelProperty3;
        private readonly ModelProperty<ModelWithNoProperties> _childModelProperty4;
        private readonly ModelProperty<ModelWithNoProperties> _childModelProperty5;
        private readonly ModelCollection<ModelWithNoProperties> _childCollectionProperty1;
        private readonly ModelCollection<ModelWithNoProperties> _childCollectionProperty2;
        private readonly ModelCollection<ModelWithNoProperties> _childCollectionProperty3;
        private readonly ModelCollection<ModelWithNoProperties> _childCollectionProperty4;
        private readonly ModelCollection<ModelWithNoProperties> _childCollectionProperty5;
        private readonly ModelCommand<Int32> _int32Command;
        private readonly ModelCommand<Char> _charCommand;

        #endregion

        #region Constructors

        public ModelForPropertyTesting()
        {
            _unconstrainedInt32 = RegisterUnconstrainedProperty<Int32>("UnconstrainedInt32");
            _unconstrainedNullableInt32 = RegisterUnconstrainedProperty<Nullable<Int32>>("UnconstrainedNullableInt32");
            _stringProperty = RegisterProperty<String>("StringProperty");
            _int32Property = RegisterProperty<Int32>("Int32Property");
            _nullableUInt32Property = RegisterProperty<Nullable<UInt32>>("NullableUInt32Property");
            _enumProperty = RegisterProperty<EnumForTesting>("EnumProperty");
            _nullableEnumProperty = RegisterProperty<Nullable<EnumForTesting>>("NullableEnumProperty");
            _stringArrayProperty = RegisterProperty<String[]>("StringArrayProperty");
            _enumerableProperty = RegisterProperty<IEnumerable<String>>("EnumerableProperty");
            _childModelProperty = RegisterProperty<ModelWithNoProperties>("ChildModelProperty");
            _childCollectionProperty1 = RegisterCollectionProperty<ModelWithNoProperties>("ChildCollectionProperty1");

            _stringProperty2 = RegisterStringProperty("StringProperty2");
            _computedStringProperty = RegisterComputedProperty<String, String>("ComputedStringProperty", CalculateComputedStringProperty, ModelBase.StandardBehaviors.RemoveBehavior(ModelPropertyBehaviors.SetsParentIsDirty), StringProperty, StringProperty2);
            _computedStringProperty2 = RegisterComputedProperty<String, String>("ComputedStringProperty2", CalculateComputedStringProperty, ModelBase.StandardBehaviors.RemoveBehavior(ModelPropertyBehaviors.SetsParentIsDirty), StringProperty, StringProperty2);
            _int32Property2 = RegisterValueTypeProperty<Int32>("Int32Property2");
            _computedInt32Property = RegisterComputedProperty<Int32>("ComputedInt32Property", CalculateComputedInt32Property, Int32Property, Int32Property2);
            _computedInt32Property2 = RegisterComputedProperty<Int32>("ComputedInt32Property2", CalculateComputedInt32Property, Int32Property, Int32Property2);
            _nullableUInt32Property2 = RegisterNullableValueTypeProperty<UInt32>("NullableUInt32Property2");
            _enumProperty2 = RegisterEnumProperty<EnumForTesting>("EnumProperty2");
            _nullableEnumProperty2 = RegisterNullableEnumProperty<EnumForTesting>("NullableEnumProperty2");
            _stringArrayProperty2 = RegisterUnconstrainedProperty<String[]>("StringArrayProperty2");
            _enumerableProperty2 = RegisterUnconstrainedProperty<IEnumerable<String>>("EnumerableProperty2");
            _childModelProperty2 = RegisterChildModelProperty<ModelWithNoProperties>("ChildModelProperty2");
            _childCollectionProperty2 = RegisterCollectionProperty<ModelWithNoProperties>("ChildCollectionProperty2");
    
            _stringProperty3 = RegisterProperty<String>("StringProperty3");
            _computedStringProperty3 = RegisterComputedProperty<String, String>("ComputedStringProperty3", CalculateComputedStringProperty, ModelPropertyBehaviors.IsResettable | ModelPropertyBehaviors.SupportsPropertyChangeCounting, StringProperty, StringProperty2);
            _computedInt32Property3 = RegisterComputedProperty<Int32, Int32>("ComputedInt32Property3", CalculateComputedInt32Property, ModelPropertyBehaviors.SetsIsDirty, Int32Property, Int32Property2);
            _int32Property3 = RegisterProperty<Int32>("Int32Property3");
            _nullableUInt32Property3 = RegisterProperty<Nullable<UInt32>>("NullableUInt32Property3");
            _enumProperty3 = RegisterProperty<EnumForTesting>("EnumProperty3");
            _nullableEnumProperty3 = RegisterProperty<Nullable<EnumForTesting>>("NullableEnumProperty3");
            _stringArrayProperty3 = RegisterProperty<String[]>("StringArrayProperty3", ModelPropertyBehaviors.SetsParentIsDirty);
            _enumerableProperty3 = RegisterProperty<IEnumerable<String>>("EnumerableProperty3", ModelPropertyBehaviors.IsResettable);
            _childModelProperty3 = RegisterProperty<ModelWithNoProperties>("ChildModelProperty3", ModelPropertyBehaviors.SetsParentIsDirty);
            _childCollectionProperty3 = RegisterCollectionProperty<ModelWithNoProperties>("ChildCollectionProperty3");

            _stringProperty4 = RegisterStringProperty("StringProperty4", ModelPropertyBehaviors.IsResettable);
            _computedStringProperty4 = RegisterComputedProperty<String, String>("ComputedStringProperty4", CalculateComputedStringProperty, ModelPropertyBehaviors.SetsIsDirty, StringProperty, StringProperty2);
            _computedInt32Property4 = RegisterComputedProperty<Int32, Int32>("ComputedInt32Property4", CalculateComputedInt32Property, ModelPropertyBehaviors.SetsIsInvalid, Int32Property, Int32Property2);
            _int32Property4 = RegisterValueTypeProperty<Int32>("Int32Property4", ModelPropertyBehaviors.SetsIsDirty);
            _nullableUInt32Property4 = RegisterNullableValueTypeProperty<UInt32>("NullableUInt32Property4", ModelPropertyBehaviors.SetsIsInvalid);
            _enumProperty4 = RegisterEnumProperty<EnumForTesting>("EnumProperty4", ModelPropertyBehaviors.SetsParentIsDirty);
            _nullableEnumProperty4 = RegisterNullableEnumProperty<EnumForTesting>("NullableEnumProperty4", ModelPropertyBehaviors.SetsParentIsInvalid);
            _stringArrayProperty4 = RegisterUnconstrainedProperty<String[]>("StringArrayProperty4", ModelPropertyBehaviors.SetsParentIsDirty | ModelPropertyBehaviors.IsResettable);
            _enumerableProperty4 = RegisterUnconstrainedProperty<IEnumerable<String>>("EnumerableProperty4", ModelPropertyBehaviors.SetsParentIsDirty);
            _childModelProperty4 = RegisterProperty<ModelWithNoProperties>("ChildModelProperty4", ModelPropertyBehaviors.SetsIsDirty);
            _childCollectionProperty4 = RegisterCollectionProperty<ModelWithNoProperties>("ChildCollectionProperty4", ModelPropertyBehaviors.SetsIsInvalid);

            _stringProperty5 = RegisterStringProperty("StringProperty5", null);
            _computedStringProperty5 = RegisterComputedProperty<String, String>("ComputedStringProperty5", CalculateComputedStringProperty, null as Nullable<ModelPropertyBehaviors>, StringProperty, StringProperty2);
            _computedInt32Property5 = RegisterComputedProperty<Int32, Int32>("ComputedInt32Property5", CalculateComputedInt32Property, null as Nullable<ModelPropertyBehaviors>, Int32Property, Int32Property2);
            _int32Property5 = RegisterValueTypeProperty<Int32>("Int32Property5", null);
            _nullableUInt32Property5 = RegisterNullableValueTypeProperty<UInt32>("NullableUInt32Property5", null);
            _enumProperty5 = RegisterEnumProperty<EnumForTesting>("EnumProperty5", null);
            _nullableEnumProperty5 = RegisterNullableEnumProperty<EnumForTesting>("NullableEnumProperty5", null);
            _stringArrayProperty5 = RegisterUnconstrainedProperty<String[]>("StringArrayProperty5", null);
            _enumerableProperty5 = RegisterUnconstrainedProperty<IEnumerable<String>>("EnumerableProperty5", null);
            _childModelProperty5 = RegisterProperty<ModelWithNoProperties>("ChildModelProperty5", null);
            _childCollectionProperty5 = RegisterCollectionProperty<ModelWithNoProperties>("ChildCollectionProperty5", null);

            _stringProperty6 = RegisterProperty<String>("StringProperty6", ModelBase.StandardBehaviors.RemoveBehavior(ModelPropertyBehaviors.IsResettable));
            _int32Command = RegisterCommand<Int32>((p1, p2) => { });
            _charCommand = RegisterCommand<Char>((p1, p2) => { });
        }

        #endregion

        #region Public

        public ModelProperty<Int32> UnconstrainedInt32
        {
            get
            {
                return _unconstrainedInt32;
            }
        }

        public ModelProperty<Nullable<Int32>> UnconstrainedNullableInt32
        {
            get
            {
                return _unconstrainedNullableInt32;
            }
        }

        public ModelProperty<String> StringProperty
        {
            get
            {
                return _stringProperty;
            }
        }
        
        public ModelProperty<String> StringProperty2
        {
            get
            {
                return _stringProperty2;
            }
        }
        
        public ModelProperty<String> StringProperty3
        {
            get
            {
                return _stringProperty3;
            }
        }

        public ModelProperty<String> StringProperty4
        {
            get
            {
                return _stringProperty4;
            }
        }

        public ModelProperty<String> StringProperty5
        {
            get
            {
                return _stringProperty5;
            }
        }

        public ModelProperty<String> StringProperty6
        {
            get
            {
                return _stringProperty6;
            }
        }

        public ModelProperty<Int32> Int32Property
        {
            get
            {
                return _int32Property;
            }
        }
        
        public ModelProperty<Int32> Int32Property2
        {
            get
            {
                return _int32Property2;
            }
        }
        
        public ModelProperty<Int32> Int32Property3
        {
            get
            {
                return _int32Property3;
            }
        }

        public ModelProperty<Int32> Int32Property4
        {
            get
            {
                return _int32Property4;
            }
        }

        public ModelProperty<Int32> Int32Property5
        {
            get
            {
                return _int32Property5;
            }
        }

        public ModelProperty<Nullable<UInt32>> NullableUInt32Property
        {
            get
            {
                return _nullableUInt32Property;
            }
        }

        public ModelProperty<Nullable<UInt32>> NullableUInt32Property2
        {
            get
            {
                return _nullableUInt32Property2;
            }
        }

        public ModelProperty<Nullable<UInt32>> NullableUInt32Property3
        {
            get
            {
                return _nullableUInt32Property3;
            }
        }

        public ModelProperty<Nullable<UInt32>> NullableUInt32Property4
        {
            get
            {
                return _nullableUInt32Property4;
            }
        }

        public ModelProperty<Nullable<UInt32>> NullableUInt32Property5
        {
            get
            {
                return _nullableUInt32Property5;
            }
        }

        public ModelProperty<EnumForTesting> EnumProperty
        {
            get
            {
                return _enumProperty;
            }
        }
        
        public ModelProperty<EnumForTesting> EnumProperty2
        {
            get
            {
                return _enumProperty2;
            }
        }
        
        public ModelProperty<EnumForTesting> EnumProperty3
        {
            get
            {
                return _enumProperty3;
            }
        }
        
        public ModelProperty<EnumForTesting> EnumProperty4
        {
            get
            {
                return _enumProperty4;
            }
        }

        public ModelProperty<EnumForTesting> EnumProperty5
        {
            get
            {
                return _enumProperty5;
            }
        }

        public ModelProperty<Nullable<EnumForTesting>> NullableEnumProperty
        {
            get
            {
                return _nullableEnumProperty;
            }
        }

        public ModelProperty<Nullable<EnumForTesting>> NullableEnumProperty2
        {
            get
            {
                return _nullableEnumProperty2;
            }
        }

        public ModelProperty<Nullable<EnumForTesting>> NullableEnumProperty3
        {
            get
            {
                return _nullableEnumProperty3;
            }
        }

        public ModelProperty<Nullable<EnumForTesting>> NullableEnumProperty4
        {
            get
            {
                return _nullableEnumProperty4;
            }
        }
        
        public ModelProperty<Nullable<EnumForTesting>> NullableEnumProperty5
        {
            get
            {
                return _nullableEnumProperty5;
            }
        }

        public ModelProperty<String> ComputedStringProperty
        {
            get
            {
                return _computedStringProperty;
            }
        }

        public ModelProperty<String> ComputedStringProperty2
        {
            get
            {
                return _computedStringProperty2;
            }
        }

        public ModelProperty<String> ComputedStringProperty3
        {
            get
            {
                return _computedStringProperty3;
            }
        }

        public ModelProperty<String> ComputedStringProperty4
        {
            get
            {
                return _computedStringProperty4;
            }
        }

        public ModelProperty<String> ComputedStringProperty5
        {
            get
            {
                return _computedStringProperty5;
            }
        }

        public ModelProperty<Int32> ComputedInt32Property
        {
            get
            {
                return _computedInt32Property;
            }
        }

        public ModelProperty<Int32> ComputedInt32Property2
        {
            get
            {
                return _computedInt32Property2;
            }
        }

        public ModelProperty<Int32> ComputedInt32Property3
        {
            get
            {
                return _computedInt32Property3;
            }
        }

        public ModelProperty<Int32> ComputedInt32Property4
        {
            get
            {
                return _computedInt32Property4;
            }
        }

        public ModelProperty<Int32> ComputedInt32Property5
        {
            get
            {
                return _computedInt32Property5;
            }
        }

        public ModelProperty<String[]> StringArrayProperty
        {
            get
            {
                return _stringArrayProperty;
            }
        }

        public ModelProperty<String[]> StringArrayProperty2
        {
            get
            {
                return _stringArrayProperty2;
            }
        }

        public ModelProperty<String[]> StringArrayProperty3
        {
            get
            {
                return _stringArrayProperty3;
            }
        }

        public ModelProperty<String[]> StringArrayProperty4
        {
            get
            {
                return _stringArrayProperty4;
            }
        }

        public ModelProperty<String[]> StringArrayProperty5
        {
            get
            {
                return _stringArrayProperty5;
            }
        }

        public ModelProperty<IEnumerable<String>> EnumerableProperty
        {
            get
            {
                return _enumerableProperty;
            }
        }

        public ModelProperty<IEnumerable<String>> EnumerableProperty2
        {
            get
            {
                return _enumerableProperty2;
            }
        }

        public ModelProperty<IEnumerable<String>> EnumerableProperty3
        {
            get
            {
                return _enumerableProperty3;
            }
        }

        public ModelProperty<IEnumerable<String>> EnumerableProperty4
        {
            get
            {
                return _enumerableProperty4;
            }
        }
        
        public ModelProperty<IEnumerable<String>> EnumerableProperty5
        {
            get
            {
                return _enumerableProperty5;
            }
        }

        public ModelProperty<ModelWithNoProperties> ChildModelProperty
        {
            get
            {
                return _childModelProperty;
            }
        }

        public ModelProperty<ModelWithNoProperties> ChildModelProperty2
        {
            get
            {
                return _childModelProperty2;
            }
        }

        public ModelProperty<ModelWithNoProperties> ChildModelProperty3
        {
            get
            {
                return _childModelProperty3;
            }
        }
        
        public ModelProperty<ModelWithNoProperties> ChildModelProperty4
        {
            get
            {
                return _childModelProperty4;
            }
        }

        public ModelProperty<ModelWithNoProperties> ChildModelProperty5
        {
            get
            {
                return _childModelProperty5;
            }
        }

        public ModelCollection<ModelWithNoProperties> ChildCollectionProperty1
        {
            get
            {
                return _childCollectionProperty1;
            }
        }

        public ModelCollection<ModelWithNoProperties> ChildCollectionProperty2
        {
            get
            {
                return _childCollectionProperty2;
            }
        }

        public ModelCollection<ModelWithNoProperties> ChildCollectionProperty3
        {
            get
            {
                return _childCollectionProperty3;
            }
        }

        public ModelCollection<ModelWithNoProperties> ChildCollectionProperty4
        {
            get
            {
                return _childCollectionProperty4;
            }
        }
        
        public ModelCollection<ModelWithNoProperties> ChildCollectionProperty5
        {
            get
            {
                return _childCollectionProperty5;
            }
        }

        public ModelCommand<Int32> Int32Command
        {
            get
            {
                return _int32Command;
            }
        }

        public ModelCommand<Char> CharCommand
        {
            get
            {
                return _charCommand;
            }
        }

        public void ValidateProperties()
        {
            ValidateRegisteredProperties();
        }

        #endregion

        #region Private

        private static Int32 CalculateComputedInt32Property(IEnumerable<ModelProperty<Int32>> properties, Int32 newPropertyValue)
        {
            return 0;
        }

        private static String CalculateComputedStringProperty(IEnumerable<ModelProperty<String>> properties, String newPropertyValue)
        {
            return String.Empty;
        }

        #endregion
    }
}
